﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using WeatherRetriever;

namespace Wakeup
{
    public partial class WeatherWakeupForm : Form
    {
        private ErrorProvider errProvider;
        private bool? retrieval_success;
        private Weather lastWeather;

        public WeatherWakeupForm()
        {
            InitializeComponent();
            errProvider = new ErrorProvider(this);
            lastWeather = null;
            retrieval_success = null;
            CancelButton = exitButton;
            autoUpdateDateTime.Format = DateTimePickerFormat.Custom;
            autoUpdateDateTime.CustomFormat = "ddd, MMM dd HH:mm";
            updateHelperTimer.Interval = WeatherWakeupSettings.Default.updateHelperTimerDelay;
            autoUpdateDateTime.MinDate = DateTime.Now;
            autoUpdateDateTime.Validating += autoUpdateDateTime_Validating;
            autoUpdateDateTime.Validated += autoUpdateDateTime_Validated;
        }

        void autoUpdateDateTime_Validated(object sender, EventArgs e)
        {
            errProvider.SetError(autoUpdateDateTime, "");
        }

        void autoUpdateDateTime_Validating(object sender, CancelEventArgs e)
        {
            if (autoUpdateDateTime.Value < DateTime.Now)
            {
                e.Cancel = true;
                errProvider.SetError(autoUpdateDateTime, "Must be set for a future time");
            }
        }

        private void PerformRetrieveWeather(object o)
        {
            try
            {
                lastWeather = WeatherGetter.GetWeather((string)o);
            }
            catch (InvalidOperationException)
            {
                retrieval_success = false;
                lastWeather = null;
                return;
            }
            retrieval_success = true;
        }

        private void PerformRetrieveWeather()
        {
            try
            {
                lastWeather = WeatherGetter.GetWeather();
            }
            catch (InvalidOperationException)
            {
                retrieval_success = false;
                lastWeather = null;
                return;
            }
            retrieval_success = true;
        }

        private void SetAllWeatherText(string txt)
        {
            asofText.Text = txt;
            conditionsText.Text = txt;
            temperatureText.Text = txt;
            feelslikeText.Text = txt;
            windText.Text = txt;
        }

        private void RetrieveCurrentWeather()
        {
            Thread t;
            SetAllWeatherText("Updating...");
            updateButton.Enabled = false;
            updateHelperTimer.Enabled = true;
            if (City_CstatRadio.Checked)
            {
                t = new Thread(new ThreadStart(PerformRetrieveWeather));
                t.Start();
            }
            else
            {
                t = new Thread(new ParameterizedThreadStart(PerformRetrieveWeather));
                t.Start(city_OtherText.Text);
            }
        }

        private void UpdateWeatherDisplay()
        {
            try
            {
                asofText.Text = lastWeather.Date.ToString();
                conditionsText.Text = lastWeather.Condition;
                temperatureText.Text = lastWeather.Temperature.ToString();
                feelslikeText.Text = lastWeather.FeelsLike.ToString();
                windText.Text = lastWeather.WindCondition.ToString();
            }
            catch (NullReferenceException)
            {
                SetAllWeatherText("ERROR-NULL REFERENCE");
            }
        }

        private void City_CstatRadio_CheckedChanged(object sender, EventArgs e)
        {
            city_OtherRadio.Checked = !City_CstatRadio.Checked;
            city_OtherText.Enabled = city_OtherRadio.Checked;
        }

        private void city_OtherRadio_CheckedChanged(object sender, EventArgs e)
        {
            City_CstatRadio.Checked = !city_OtherRadio.Checked;
            city_OtherText.Enabled = city_OtherRadio.Checked;
        }

        private void exitButton_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        private void updateButton_Click(object sender, EventArgs e)
        {
            RetrieveCurrentWeather();
        }

        private void browseButton_Click(object sender, EventArgs e)
        {
            selectMusicDialog.ShowDialog();
        }

        private void selectMusicDialog_FileOk(object sender, CancelEventArgs e)
        {
            musicFilepath.Text = selectMusicDialog.FileName;
        }

        private void startMusicCheck_CheckedChanged(object sender, EventArgs e)
        {
            browseButton.Enabled = musicFilepath.Enabled = startMusicCheck.Checked;
        }

        private void autoUpdateTimer_Tick(object sender, EventArgs e)
        {
            long ticks = autoUpdateDateTime.Value.Subtract(DateTime.Now).Ticks;
            if (ticks <= 0)
            {
                RetrieveCurrentWeather();
                stopTimerButton.Enabled = false;
                startTimerButton.Enabled = true;
                autoUpdateTimer.Enabled = false;
                if (startMusicCheck.Checked)
                {
                    // The following code segment will only play .wav files
                    ///*
                    System.Media.SoundPlayer player = new System.Media.SoundPlayer(@"C:\Users\Will\Game Isos\skyrim\1111_rld-skyrim_update4\rld-skyru4\Originals\MainTitle.wav");
                    player.PlaySync();
                    //*/
                    axWindowsMediaPlayer1.URL = musicFilepath.Text;
                }
            }
            /*
             * BROKEN - Attempt to set the interval of the
             * timer appropriate to prevent more ticks than is necessary
             * See also the broken code in startTimerButton_Click
             */
            //else if (ticks > (long)int.MaxValue)
            //{
            //    autoUpdateTimer.Interval = int.MaxValue;
            //}
            //else
            //{
            //    autoUpdateTimer.Interval = (int)ticks;
            //}
        }

        private void startTimerButton_Click(object sender, EventArgs e)
        {
            // TODO - Round down to the nearest second
            //autoUpdateDateTime.Value.AddSeconds(autoUpdateDateTime.Value.Second * -1);    // Does not appear to have any effect
            autoUpdateTimer.Enabled = true;
            /*
             * BROKEN - Attempt to set the interval of the timer
             * appropriately to prevent more ticks than is necessary
             * If uncommented, this will result in the timer's tick event never being triggered
             * See also the broken code in autoUpdateTimer_Tick
             */
            //long ticks = (autoUpdateDateTime.Value.Subtract(DateTime.Now)).Ticks;
            //if (ticks > (long)int.MaxValue)
            //    autoUpdateTimer.Interval = int.MaxValue;
            //else
            //    autoUpdateTimer.Interval = (int)ticks;

            startTimerButton.Enabled = false;
            stopTimerButton.Enabled = true;
            autoUpdateDateTime.Enabled = false;
        }

        private void stopTimerButton_Click(object sender, EventArgs e)
        {
            startTimerButton.Enabled = true;
            stopTimerButton.Enabled = false;
            alarmgroupbox.Enabled = true;
            autoUpdateDateTime.Enabled = true;
            autoUpdateTimer.Enabled = false;
        }

        private void updateHelperTimer_Tick(object sender, EventArgs e)
        {
            bool success;
            if (!retrieval_success.HasValue)
                return;
            else
                success = retrieval_success.GetValueOrDefault();

            if (success)
            {
                UpdateWeatherDisplay();
            }
            else
            {
                SetAllWeatherText("ERROR - COULD NOT RETRIEVE");
            }

            retrieval_success = null;
            updateButton.Enabled = true;
            updateHelperTimer.Enabled = false;
        }

        private void autoUpdateDateTime_ValueChanged(object sender, EventArgs e)
        { }
    }
}
